﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;

namespace SimpleFileManager.Manager
{
    public partial class FileManager
    {
        private FilePanel _activePanel;
        private FilePanel _inactivePanel;

        private static List<string> systemPaths = new List<string>() { "My computer" };

        public event FolderActionEventHandler OnChangeFolder;
        public event FolderActionEventHandler OnSortPanelItems;
        public event EventHandler OnChangePanels;

        [Serializable]
        private class FileManagerMemento : IFileManagerMemento
        {
            private readonly IFilePanelMemento _leftPanelMemento;
            private readonly IFilePanelMemento _rightPanelMemento;

            public FileManagerMemento(FileManager fileManager)
            {
                _leftPanelMemento = fileManager._activePanel.GetState();
                _rightPanelMemento = fileManager._inactivePanel.GetState();
            }

            public void Restore(FileManager fileManager)
            {
                _leftPanelMemento.Restore(fileManager._activePanel);
                _rightPanelMemento.Restore(fileManager._inactivePanel);
            }
        }

        public FileManager()
        {
            _activePanel = new FilePanel(this);
            _inactivePanel = new FilePanel(this);
        }

        private IFileManagerMemento GetState()
        {
            return new FileManagerMemento(this);
        }

        public IFolderIterator GetDrives()
        {
            FolderIterator itr = new FolderIterator(systemPaths[0]);
            foreach (DriveInfo drive in DriveInfo.GetDrives())
            {
                itr.Add(FilePanelItemFactory.CreateDrive(drive.Name));
            }
            return itr;
        }

        public void SaveState(string path)
        {
            Stream fileStream = System.IO.File.Create(path);
            BinaryFormatter serializer = new BinaryFormatter();
            try
            {
                serializer.Serialize(fileStream, this.GetState());
            }
            catch (Exception)
            {
                throw;
            }
            finally
            {
                fileStream.Close();
            }
        }

        public void LoadState(string path)
        {
            if (System.IO.File.Exists(path))
            {
                Stream fileStream = System.IO.File.OpenRead(path);
                try
                {
                    BinaryFormatter deserializer = new BinaryFormatter();
                    FileManagerMemento memento = (FileManagerMemento)deserializer.Deserialize(fileStream);
                    memento.Restore(this);
                    _activePanel.Refresh();
                    InitiateChangePanels();
                    _activePanel.Refresh();
                }
                catch (Exception)
                {
                    throw;
                }
                finally
                {
                    fileStream.Close();
                }
            }
            else
            {
                string defPath = Environment.CurrentDirectory;
                _activePanel.ChangeFolder(defPath);
                _inactivePanel.ChangeFolder(defPath);
            }
        }

        private bool IsPanelActive(FilePanel panel)
        {
            return panel.Equals(_activePanel);
        }

        private void InitiateChangePanels()
        {
            ChangePanels();
            if (OnChangePanels != null)
            {
                OnChangePanels(this, new EventArgs());
            }
        }

        public void ChangePanels()
        {
            FilePanel tmp = _activePanel;
            _activePanel = _inactivePanel;
            _inactivePanel = tmp;
        }

        public void Refresh()
        {
            _activePanel.Refresh();
        }

        public void GoBackward()
        {
            _activePanel.GoBackward();
        }

        public void GoForward()
        {
            _activePanel.GoForward();
        }

        public void MakeAction(IFilePanelItem item)
        {
            _activePanel.MakeAction(item);
        }

        public void ApplyFileFilter(string searchPattern)
        {
            _activePanel.ApplyFileFilter(searchPattern);
        }

        public void GoToParentFolder()
        {
            _activePanel.GoToParentFolder();
        }

        public void GoToRootFolder()
        {
            _activePanel.GoToRootFolder();
        }

        public void Rename(IFilePanelItem item,string newName)
        {
            item.Rename(newName);
        }

        public void Copy(IFilePanelItem item)
        {
            item.Copy(_inactivePanel.CurrentFolder);
        }

        public void Move(IFilePanelItem item)
        {
            item.Move(_inactivePanel.CurrentFolder);
        }

        public void Delete(IFilePanelItem item)
        {
            item.Delete();
            _inactivePanel.Refresh();
        }

        public void SortPanelItems(Comparison<IFilePanelItem> comparer)
        {
            _activePanel.SortPanelItems(comparer);
            _activePanel.Refresh();
            _inactivePanel.Refresh();
        }

        internal void Create(IFilePanelItem item)
        {
            item.Create(_activePanel.CurrentFolder);
        }
    }
}
